home *** CD-ROM | disk | FTP | other *** search
/ CD-ROM Today - The Disc! 8 / cdrt08.iso / mac / Shareware / HyperCard / demoCdef 120 ƒ / demo Source ƒ / demoCDEF.c next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  20.4 KB  |  741 lines  |  [TEXT/KAHL]

  1. // -----------------------------------------------------------------------------
  2. //    File        : demoCDEF.c
  3. //    Date        : August 24, 1994
  4. //    Author        : Jim Stout
  5. //    Purpose        : A demonstration routine for :
  6. //                    - my collection of CDEF's
  7. //                    - dialogAssist.c dialog utilities
  8. //                    - panelAssist.c tabPanel CDEF handling
  9. //                    - movableModal.c dialog routines
  10. //
  11. //    Note the special usage of dim text routines required when using
  12. //    AppendDITL and ShortenDITL routines.  See file dimText.c.
  13. //
  14. //    This demo uses the "TabPanel" CDEF - see "About CDEF's╔".
  15. //
  16. // -----------------------------------------------------------------------------
  17. #include <GestaltEqu.h>
  18. #include <stdio.h>
  19.  
  20. #include "demoCDEF.h"
  21. #include "jimsCDEF.h"
  22. #include "dialogAssist.h"
  23. #include "dimText.h"
  24. #include "panelAssist.h"
  25. #include "movableModal.h"
  26. #include "TogLib.h"
  27.  
  28. #if THINK_C == 7
  29. #define ProcPtr ControlActionUPP
  30. #endif
  31.  
  32. // -----------------------------------------------------------------------------
  33. // temporary storage for control values
  34. // -----------------------------------------------------------------------------
  35. short buttonValue[14];
  36. short popUpValue[4];
  37. short spinnerValue[6];
  38. long  dateValue[6];
  39. short hSliderValue[5];
  40. short vSliderValue[6];
  41. short progressValue[8];
  42.  
  43. // -----------------------------------------------------------------------------
  44. // local routines
  45. // -----------------------------------------------------------------------------
  46.  
  47. static void            demoPanel        (void);
  48. static void            processPanel    (DialogPtr theDialog, short currPanel, 
  49.                                         short itemHit);
  50. static void            savePanel        (DialogPtr theDialog, short toPanel);
  51. static void            restorePanel    (DialogPtr theDialog, short toPanel);
  52. static pascal char    filter            (DialogPtr theDialog, EventRecord *theEvent, 
  53.                                         short *theItem);
  54. static pascal void    trackSpin        (ControlHandle c, short p);
  55. static pascal void    trackSlider        (ControlHandle c, short p);
  56. static pascal void    trackSpin6        (ControlHandle c, short p);
  57. static void         setNewFont        (DialogPtr theDialog, short newFont, 
  58.                                         long newSize);
  59. static void            setNewSize        (DialogPtr theDialog, long newSize);
  60.  
  61. // -----------------------------------------------------------------------------
  62. // routine called by movableModalDialog, replace with a real one╔
  63. // -----------------------------------------------------------------------------
  64.  
  65. extern void updateWindow(WindowPtr);
  66.  
  67. extern void updateWindow(WindowPtr w)
  68. {
  69.     SetPort(w);
  70.     BeginUpdate(w);
  71.     EndUpdate(w);
  72. }
  73.  
  74. // -----------------------------------------------------------------------------
  75. // Mainline starts here :)
  76. // -----------------------------------------------------------------------------
  77.  
  78. main()
  79. {
  80.     InitGraf(&thePort);
  81.     InitWindows();
  82.     InitFonts();
  83.     InitMenus();
  84.     TEInit();
  85.     InitCursor();
  86.     InitDialogs(0L);    
  87.  
  88.     if(!daGestalt(gestaltDITLExtAttr))
  89.         StopAlert(256, nil); 
  90.     else
  91.         demoPanel();
  92. }
  93.  
  94. // -----------------------------------------------------------------------------
  95. // demo the tab dialog panel
  96. // -----------------------------------------------------------------------------
  97. static void demoPanel()
  98. {
  99.  
  100.     DialogPtr        theDialog;
  101.     short            itemHit, inx, currPanel=0,toPanel;
  102.     Handle            h;
  103.     Rect            r;
  104.     Boolean            dimIt = true;
  105.     
  106.     theDialog = GetNewDialog(128,0L,(DialogPtr)-1);
  107.     if(theDialog) {
  108.     
  109.         SetPort(theDialog);    
  110.         initDimText(theDialog);                    // set up for dimmable text
  111.         
  112. // initialize the dialog to the correct panel
  113.  
  114.         toPanel = daGetCtlValue(theDialog, TABCNTL);
  115.         
  116.         disposeDimData(theDialog);
  117.         panelSwap(theDialog, currPanel, toPanel, DITLBASE);
  118.         makeDimmable(theDialog);
  119.         
  120. // a "real" application would probably get control settings from some sort
  121. // of configuration file/record/structure.  We'll just initialize our stuff
  122. // by calling savePanel() which will take the values from the CNTL templates.
  123.  
  124.         savePanel(theDialog, toPanel);
  125.         
  126. // restore control settings and initialize the panel.
  127.  
  128.         restorePanel(theDialog, toPanel);
  129.         currPanel = toPanel;
  130.         
  131. // show the dialog and start handling events
  132.  
  133.         ShowWindow(theDialog);
  134.         
  135.         do {
  136.         
  137.             movableModalDialog    ((filterProc)filter,&itemHit);
  138.             
  139. // a click on a tab, change to that panel
  140.  
  141.             if(itemHit == TABCNTL) {
  142.             
  143.                 toPanel = daGetCtlValue(theDialog, TABCNTL);
  144.                 
  145.                 if(toPanel != currPanel) {
  146.                 
  147. // save settings of current panel first
  148.         
  149.                     savePanel(theDialog, currPanel);
  150.                 
  151. // switch to the new panel and restore/initialize it
  152.  
  153.                     disposeDimData(theDialog);
  154.                     panelSwap(theDialog, currPanel, toPanel, DITLBASE);
  155.                     makeDimmable(theDialog);
  156.  
  157.                     restorePanel(theDialog, toPanel);
  158.                 
  159.                     currPanel = toPanel;
  160.                 
  161. // change the Disable/Enable button if needed
  162.  
  163.                     if(!dimIt) {
  164.                         daDimOne(theDialog, DISABLE, false);
  165.                         daSetCtlTitle(theDialog, DISABLE, "\pDisable");
  166.                         dimIt = true;
  167.                     }
  168.                 }
  169.             }
  170.             else
  171.  
  172. // show what the disabled controls look like
  173.  
  174.             if(itemHit == DISABLE) {
  175.                 if(dimIt)
  176.                     daSetCtlTitle(theDialog, DISABLE, "\pEnable");
  177.                 else
  178.                     daSetCtlTitle(theDialog, DISABLE, "\pDisable");
  179.                 inx = CountDITL(theDialog);
  180.                 daDimItems(theDialog, DITLBASE+1, inx, dimIt);
  181.                 dimIt = !dimIt;
  182.                 if(currPanel == 1)
  183.                     daDimOne(theDialog, PB1, true);
  184.             }
  185.             else
  186.             
  187. // handle a click on a control within a panel
  188.  
  189.                 processPanel(theDialog, currPanel, itemHit);
  190.                 
  191.         }while(itemHit != ok && itemHit != cancel);
  192.     
  193.         if(itemHit == OK) {
  194. //            savePanel(theDialog, currPanel);
  195. //    some code to apply the temporary storage control values
  196. //    in your application could go here.
  197.         }    
  198.         disposeDimText(theDialog);
  199.         DisposDialog(theDialog);
  200.     }
  201. }
  202.  
  203. // -----------------------------------------------------------------------------
  204. // Handle a click on a control
  205. // -----------------------------------------------------------------------------
  206. static void processPanel(DialogPtr theDialog, short currPanel, short itemHit)
  207. {
  208.     ControlHandle        h;
  209.     short                t, val, newFont;
  210.     Rect                r;
  211.     long                num, newSize;
  212.     Str255                fontName,fontSize;
  213.     unsigned long        secs;
  214.     popUpPrivateDataH    hPpd;
  215.     
  216.     switch (currPanel) {
  217.         case BUTTONS:
  218.             switch(itemHit) {
  219.                 case CB1:                // click on a checkBox
  220.                 case CB2:
  221.                 case CB3:
  222.                 case CB4:
  223.                     daToggleCheck(theDialog, itemHit);
  224.                     resetTogButtons(theDialog,TB1);
  225.                 break;
  226.                 case RB1:                // click on a radioButton
  227.                 case RB2:
  228.                 case RB3:
  229.                 case RB4:
  230.                     daToggleRadio(theDialog, itemHit, RB1, RB4);
  231.                     resetTogButtons(theDialog,TB1);
  232.                 break;
  233.                 case TB1:                // click on a TogButton
  234.                 case TB2:
  235.                 case TB3:
  236.                 case TB4:
  237.                     setTogButtons(theDialog, itemHit, TB1, TB4);
  238.                 break;
  239.                 case EDITSIZE:            // keydown in edit text
  240.                     num = daGetINum(theDialog, EDITSIZE);
  241.                     setNewSize(theDialog, num);
  242.                     resetTogButtons(theDialog,TB1);
  243.                 break;
  244.                 case SIZEPOP:
  245.                     GetDItem(theDialog,SIZEPOP,&t,(Handle *)&h,&r);
  246.                     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  247.                     
  248.                     newSize = GetCtlValue(h);
  249.                     GetItem((*hPpd)->mHandle, newSize, fontSize);
  250.                     daSetIText(theDialog, EDITSIZE, fontSize);
  251.                     daSelIText(theDialog, EDITSIZE);
  252.                     resetTogButtons(theDialog,TB1);
  253.                 break;
  254.                 case SETFONT:
  255.                 
  256. // get the font size from the popup menu
  257.  
  258.                     GetDItem(theDialog,SIZEPOP,&t,(Handle *)&h,&r);
  259.                     val = GetCtlValue(h);
  260.                     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  261.                     GetItem((*hPpd)->mHandle, val, fontSize);
  262.                     StringToNum(fontSize, &newSize);
  263.  
  264. // get the font from the popup menu
  265.     
  266.                     GetDItem(theDialog,FONTPOP,&t,(Handle *)&h,&r);
  267.                     val = GetCtlValue(h);
  268.                     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  269.                     GetItem((*hPpd)->mHandle, val, fontName);
  270.                     GetFNum(fontName, &newFont);
  271.                     setNewFont(theDialog, newFont, newSize);
  272.                     resetTogButtons(theDialog,TB1);
  273.                 break;
  274.             }
  275.         break;
  276.  
  277. // set the value of the arrow control to match the edit text item
  278.  
  279.         case SPINNERS:
  280.             if(itemHit == EDITSPIN) {
  281.                 num = daGetINum(theDialog, EDITSPIN);
  282.                 daSetCtlValue(theDialog, SPIN3, (short)num);
  283.             }
  284.         break;
  285.         
  286. // reset the date time controls if RESET button clicked
  287.  
  288.         case DATETIME:
  289.             if(itemHit == RESET) {
  290.                 GetDateTime(&secs);                        // new date/time
  291.                 for(t=1;t<=6;t++) {
  292.                     h = daGetCtlHandle(theDialog, t+DITLBASE);
  293.                     if(h) {
  294.                         SetCRefCon(h, secs);            // tell control about it
  295.                         InvalRect(&(**h).contrlRect);    // force redraw
  296.                     }
  297.                 }
  298.             }
  299.         break;
  300.         
  301. // show how a spinner control can adjust a progress bar control
  302.  
  303.         case PROGBARS:
  304.             if(itemHit == SPIN10) {
  305.                 daSetCtlValue(theDialog, PROG9, 
  306.                     daGetCtlValue(theDialog, SPIN10));
  307.             }
  308.         break;
  309.         
  310. // we don't do any special processing for the other control examples.
  311.  
  312.         case POPUPS:
  313.         break;
  314.         case HSLIDERS:
  315.         break;
  316.         case VSLIDERS:
  317.         break;
  318.     }
  319. }
  320. // -----------------------------------------------------------------------------
  321. // A sample routine to show one method of saving the settings of the controls
  322. // on a panel. When a panel is "dismissed", the Dialog Manager disposes of the 
  323. // controls on the panel, so we have to save the values to restore if the panel
  324. // is displayed again.
  325. //
  326. // This is pretty "brute force" - just some global arrays of control values.
  327. //
  328. // -----------------------------------------------------------------------------
  329. static void savePanel(DialogPtr theDialog, short currPanel)
  330. {
  331.     ControlHandle    h;
  332.     Rect            r;
  333.     short            t,inx;
  334.     
  335.     switch (currPanel) {
  336.         case BUTTONS:
  337.             for(inx=1;inx<=12;inx++)
  338.                 buttonValue[inx-1] = daGetCtlValue(theDialog, inx+DITLBASE);
  339.             buttonValue[12] = daGetINum(theDialog, EDITSIZE);
  340.             buttonValue[13] = daGetCtlValue(theDialog, FONTPOP);
  341.         break;
  342.         case POPUPS:
  343.             for(inx=1;inx<=4;inx++)
  344.                 popUpValue[inx-1] = daGetCtlValue(theDialog, inx+DITLBASE);
  345.         break;
  346.         case SPINNERS:
  347.             for(inx=1;inx<=6;inx++)
  348.                 spinnerValue[inx-1] = daGetCtlValue(theDialog, inx+DITLBASE);
  349.         break;
  350.         case DATETIME:
  351.             for(inx=1;inx<=6;inx++)
  352.                 dateValue[inx-1] = daGetCtlRefCon(theDialog, inx+DITLBASE);
  353.         break;
  354.         case HSLIDERS:
  355.             for(inx=1;inx<=5;inx++)
  356.                 hSliderValue[inx-1] = daGetCtlValue(theDialog, inx+DITLBASE);
  357.         break;
  358.         case VSLIDERS:
  359.             for(inx=1;inx<=6;inx++)
  360.                 vSliderValue[inx-1] = daGetCtlValue(theDialog, inx+DITLBASE);
  361.         break;
  362.         case PROGBARS:
  363.             for(inx=1;inx<=8;inx++)
  364.                 progressValue[inx-1] = daGetCtlValue(theDialog, inx+DITLBASE);
  365.         break;
  366.     }
  367. }
  368.  
  369. // -----------------------------------------------------------------------------
  370. // A sample routine to show one method of restoring the control settings to
  371. // proper values when a panel is shown by clicking on its tab.
  372. //
  373. // This routine also does some special initialization of controls.
  374. // -----------------------------------------------------------------------------
  375. static void restorePanel(DialogPtr theDialog, short toPanel)
  376. {
  377.     ControlHandle    ch;
  378.     SpinHandle        hSpin;
  379.     Rect            r;
  380.     short            t,inx;
  381.     long            l;
  382.  
  383.     switch(toPanel) {
  384.     
  385.         case BUTTONS:
  386.  
  387. // restore control values
  388.  
  389.             for(inx=1;inx<=12;inx++)
  390.                 daSetCtlValue(theDialog, inx+DITLBASE, buttonValue[inx-1]);
  391.             daSetINum(theDialog, EDITSIZE, buttonValue[12]);
  392.             setNewSize(theDialog, buttonValue[12]);
  393.             daSetCtlValue(theDialog, FONTPOP, buttonValue[13]);
  394.                 
  395. // initialize the Tog buttons and disable one button
  396.  
  397.             initTogButtons(theDialog, TB1,TB4);
  398.             daDimOne(theDialog, PB1, true);
  399.         break;
  400.         
  401.         case POPUPS:
  402.         
  403. // set font & restore control values
  404.  
  405.             TextFont(systemFont);
  406.             TextSize(0);
  407.             for(inx=1;inx<=4;inx++)
  408.                 daSetCtlValue(theDialog, inx+DITLBASE, popUpValue[inx-1]);
  409.         break;
  410.         
  411.         case SPINNERS:
  412.         
  413. // set font & restore control values
  414.  
  415.             setNewFont(theDialog, 0, 0);
  416.             
  417.             for(inx=1;inx<=6;inx++)
  418.                 daSetCtlValue(theDialog, inx+DITLBASE, spinnerValue[inx-1]);
  419.             
  420. // initialize edit text item to the value of the 3rd spinner
  421.  
  422.             daSetINum(theDialog, EDITSPIN, 
  423.                         daGetCtlValue(theDialog,  SPIN3));
  424.             SelIText(theDialog, EDITSPIN, 32768, 32768);
  425.             
  426. // the 6th spinner will adjust by 0.10, so stash a divisor value of 10
  427. // in the userData field
  428.  
  429.             ch = daGetCtlHandle(theDialog, SPIN6);
  430.             if(ch) {
  431.                 hSpin = (SpinHandle)(**ch).contrlData;
  432.                 (**hSpin).userData = 10;
  433.                 trackSpin6(ch, 1);                // draw the value
  434.             }
  435.             
  436.         break;
  437.         
  438.         case DATETIME:
  439.  
  440. // set font & restore control values
  441.  
  442.             TextFont(geneva);
  443.             TextSize(9);
  444.             for(inx=1;inx<=6;inx++)
  445.                 daSetCtlRefCon(theDialog, inx+DITLBASE, dateValue[inx-1]);
  446.         break;    
  447.         
  448.         case HSLIDERS:
  449.  
  450. // set font & restore control values
  451.  
  452.             TextFont(geneva);
  453.             TextSize(9);
  454.             for(inx=1;inx<=5;inx++)
  455.                 daSetCtlValue(theDialog, inx+DITLBASE, hSliderValue[inx-1]);
  456.                 
  457. // set a ctlAction proc for slider 3
  458.             
  459.             ch = daGetCtlHandle(theDialog, HSLIDER3);
  460.             SetCtlAction(ch, (ProcPtr)trackSlider);        // or (ControlActionUPP)
  461.             daSetINum(theDialog, HSLIDERVAL, GetCtlValue(ch));
  462.         break;    
  463.         
  464.         case VSLIDERS:
  465.             TextFont(geneva);
  466.             TextSize(9);
  467.  
  468. // restore control values
  469.  
  470.             for(inx=1;inx<=6;inx++)
  471.                 daSetCtlValue(theDialog, inx+DITLBASE, vSliderValue[inx-1]);
  472.                 
  473. // set a ctlAction proc for slider 5
  474.             
  475.             ch = daGetCtlHandle(theDialog, VSLIDER5);
  476.             SetCtlAction(ch, (ProcPtr)trackSlider);
  477.             daSetINum(theDialog, VSLIDERVAL, GetCtlValue(ch));
  478.         break;    
  479.         
  480.         case PROGBARS:
  481.         
  482. // set font & restore control values
  483.  
  484.             TextFont(geneva);
  485.             TextSize(9);
  486.             for(inx=1;inx<=8;inx++)
  487.                 daSetCtlValue(theDialog, inx+DITLBASE, progressValue[inx-1]);
  488.         break;    
  489.     }
  490. }
  491. // -----------------------------------------------------------------------------
  492. //    a simple dialog filter proc
  493. // -----------------------------------------------------------------------------
  494. static  pascal char filter(DialogPtr theDialog, EventRecord *theEvent, short *theItem)
  495. {
  496.     char             result = FALSE;
  497.     char             c;
  498.     short            panelNum,inx,editItem,partCode;
  499.     long            min,max;
  500.     ControlHandle    cHdl;
  501.     Point            mousePt;
  502.     
  503.     switch(theEvent->what) {
  504.         
  505.         panelNum = daGetCtlValue(theDialog, TABCNTL);
  506.         
  507.         case nullEvent:
  508.         
  509. // for this demo program, we'll use null events to demo the progress bar
  510. // cdefs on panel 7 of the dialog
  511.  
  512.             if(panelNum == PROGBARS) {
  513.                 for(inx=DITLBASE+1;inx<=DITLBASE+8;inx++) {
  514.                     daSetCtlValue(theDialog, inx, 
  515.                                     daGetCtlValue(theDialog, inx)+1);
  516.                     if(daGetCtlValue(theDialog, inx) >= daGetCtlMax(theDialog, inx))
  517.                         daSetCtlValue(theDialog, inx, 0);
  518.                 }
  519.             }
  520.         break;
  521.  
  522.         
  523.         case keyDown:
  524.          case autoKey:
  525.  
  526. // for this demo, we'll show how to use command or control key 
  527. // combinations to operate the tabPanel CDEF
  528.  
  529.              c = theEvent->message & charCodeMask;
  530.              
  531.             if(theEvent->modifiers & cmdKey) {
  532.                  if(result = panelCmdKey(theDialog, TABCNTL, c, theItem))
  533.                      break;
  534.              }
  535.             if(theEvent->modifiers & controlKey ||
  536.                 theEvent->modifiers & cmdKey) {
  537.                  if(result = panelCmdTab(theDialog, TABCNTL, c, theItem))
  538.                      break;
  539.              }
  540.              if(result = daExitKey(theDialog, theEvent, theItem, cancel))
  541.                  break;
  542.  
  543. // handle a forward delete key
  544.                  
  545.              if(result = daForwardDel(theDialog, c))
  546.                  break;
  547.              if(theEvent->modifiers & shiftKey) {
  548.                  if(result = daShiftSelect(theDialog, c))
  549.                      break;
  550.              }
  551.             editItem = ((DialogPeek)theDialog)->editField + 1;
  552.             
  553. // limit to numeric entry only
  554.  
  555.             if(panelNum == BUTTONS && editItem == EDITSIZE) {
  556.                 result = daEnterNumber(theDialog, editItem, 1L, 18L, c);
  557.             }
  558.             else 
  559.             if(panelNum == SPINNERS) {
  560.                 max = daGetCtlMax(theDialog, SPIN3);
  561.                 min = daGetCtlMin(theDialog, SPIN3);
  562.                 result = daEnterNumber(theDialog, editItem, min, max, c);
  563.             }
  564.          break;
  565.          
  566.          case mouseDown:
  567.             mousePt = theEvent->where;
  568.             GlobalToLocal(&mousePt);
  569.             partCode = FindControl(mousePt, theDialog, &cHdl);
  570.  
  571.  // demonstrate use of FindControl/TrackControl within a dialog and to show
  572.  // how to continuously update the progress bar (item #10) from the value 
  573.  // of the spinner (item #9)
  574.  
  575.              if(panelNum == PROGBARS) {
  576.                 if(partCode && cHdl == daGetCtlHandle(theDialog, SPIN10)) {
  577.                     TrackControl(cHdl, mousePt,  (ProcPtr)trackSpin);
  578.                 }
  579.              }
  580.              else
  581.  
  582.  // have spinner 6 is a control that adjusts by a fractional value
  583.  
  584.              if(panelNum == SPINNERS) {
  585.                 if(partCode && cHdl == daGetCtlHandle(theDialog, SPIN6)) {
  586.                     TrackControl(cHdl, mousePt,  (ProcPtr)trackSpin6);
  587.                 }
  588.              }
  589.      
  590.          break;
  591.     }
  592.     return result;
  593. }
  594. //---------------------------------------------------------------------------------- 
  595. //    A simple action proc for call to TrackControl above.  Just sets the value
  596. //  of the progress bar to match the spinner.
  597. //----------------------------------------------------------------------------------
  598.  
  599. static pascal void trackSpin(ControlHandle theControl, short partCode)
  600. {
  601.     DialogPtr theDialog = (**theControl).contrlOwner;
  602.     
  603.     if(partCode) {
  604.         daSetCtlValue(theDialog, PROG9, GetCtlValue(theControl));
  605.     }
  606. }
  607. //---------------------------------------------------------------------------------- 
  608. //    This routine is set as an actionProc via SetCtlAction to provide
  609. //  "live" display of the values of a Slider control
  610. //----------------------------------------------------------------------------------
  611.  
  612. static pascal void trackSlider(ControlHandle theControl, short partCode)
  613. {
  614.     DialogPtr theDialog = (**theControl).contrlOwner;
  615.     
  616.     if(partCode) {
  617.         if(theControl == daGetCtlHandle(theDialog, VSLIDER5))
  618.             daSetINum(theDialog, VSLIDERVAL, GetCtlValue(theControl));
  619.         else
  620.         if(theControl == daGetCtlHandle(theDialog, HSLIDER3))
  621.             daSetINum(theDialog, HSLIDERVAL, GetCtlValue(theControl));
  622.     }
  623. }
  624. //---------------------------------------------------------------------------------- 
  625. //    This Action proc shows how to have a spinner control with a fractional
  626. //  increment
  627. //----------------------------------------------------------------------------------
  628.  
  629. static pascal void trackSpin6(ControlHandle theControl, short partCode)
  630. {
  631.     DialogPtr        theDialog;
  632.     short            val,div;
  633.     ControlHandle    hCtrl;
  634.     SpinHandle        hSpin;
  635.     Str255            s;
  636.     double            dbl;
  637.     
  638.     if(!partCode)                    // avoid flicker
  639.         return;
  640.         
  641.     theDialog = (**theControl).contrlOwner;
  642.     
  643. // grab the handle to the control, extract the userData value
  644. // to use as divisor to calculate the value to display in the text item
  645.  
  646.     hCtrl = daGetCtlHandle(theDialog, SPIN6);
  647.     if(theControl == hCtrl) {
  648.         hSpin = (SpinHandle)(**theControl).contrlData;
  649.         div = (**hSpin).userData;
  650.         
  651.         val = GetCtlValue(hCtrl);
  652.         dbl = (double)val/div;
  653.         
  654.         sprintf((char *)s, "%3.1lf", dbl);
  655.         CtoPstr((char *)s);
  656.         
  657. // display the calcuated value (in this case, via a statText item)
  658.  
  659.         daSetIText(theDialog, FRACTSPIN, s);
  660.     }
  661.         
  662. }
  663. //---------------------------------------------------------------------------------- 
  664. //    Set a new font for this dialog.  This is a nasty way to do this,
  665. //  but it appears to work.
  666. //----------------------------------------------------------------------------------
  667.  
  668. static void setNewFont(DialogPtr theDialog, short newFont, long newSize)
  669. {
  670.     FontInfo            fInfo;
  671.  
  672. // set new font & size for current port
  673.     
  674.     TextFont(newFont);
  675.     TextSize((short)newSize);
  676.  
  677. // set new font for TEHandle in dialog (this is a crude hack!)
  678.     
  679.     GetFontInfo(&fInfo);
  680.     (*((DialogPeek)theDialog)->textH)->txFont = newFont;
  681.     (*((DialogPeek)theDialog)->textH)->txSize = newSize;
  682.     (*((DialogPeek)theDialog)->textH)->fontAscent = fInfo.ascent;
  683.  
  684. // redraw the dialog in the new font & size
  685.     
  686.     DrawDialog(theDialog);
  687. }
  688.  
  689. //---------------------------------------------------------------------------------- 
  690. //    Set a new size into the popup menu for font size.  Called when the 
  691. //    EDITSIZE dialog edit item is changed, will add or remove a "custom" size
  692. //    and a separator line as required.
  693. //----------------------------------------------------------------------------------
  694. static void    setNewSize    (DialogPtr theDialog, long newSize)
  695. {
  696.     short                type,val,inx,max;
  697.     long                longVal;
  698.     ControlHandle        h;
  699.     MenuHandle            hMenu;
  700.     Rect                r;
  701.     popUpPrivateDataH    hPpd;
  702.     Str255                s;
  703.     Boolean                found=false;
  704.     
  705.     GetDItem(theDialog,SIZEPOP,&type,(Handle *)&h,&r);    // get menu handle
  706.     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  707.     hMenu = (*hPpd)->mHandle;
  708.     
  709.     val = GetCtlValue(h);                                // uncheck current item
  710.     CheckItem(hMenu, val, FALSE);
  711.     
  712.     max = CountMItems(hMenu);                            // number of menu items
  713.     
  714.     for(inx=1;inx<=max;inx++) {                            // see if typed in value
  715.         GetItem(hMenu, inx, s);                            // matches a menu item
  716.         StringToNum(s, &longVal);
  717.         if(longVal == newSize) {                        // yep, got a match but it is
  718.             if(inx > 2 & max > MAXFONTSIZES) {            // not custom, so let's
  719.                 DelMenuItem(hMenu,1);                    // delete the custom setting
  720.                 DelMenuItem(hMenu,1);                    // and the separator line
  721.                 inx-=2;
  722.             }
  723.             CheckItem(hMenu, inx, TRUE);                // check new item
  724.             SetCtlValue(h, inx);
  725.             found = true;
  726.             break;
  727.         }
  728.     }
  729.     if(!found) {                                        // no match, set custom item
  730.         NumToString(newSize, s);
  731.         if(max == MAXFONTSIZES) {                        // add a custom value
  732.             InsMenuItem(hMenu, "\p(-", 0);                // first, a separator
  733.             InsMenuItem(hMenu, s, 0);                    // now, the new size
  734.         }
  735.         else {
  736.             SetItem(hMenu, 1, s);                        // replace existing custom
  737.         }
  738.         CheckItem(hMenu, 1, TRUE);
  739.         SetCtlValue(h, 1);
  740.     }
  741. }